home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / c / gcc / pmlsrc23.zoo / pmltests / c2c.c next >
Encoding:
C/C++ Source or Header  |  1994-03-19  |  11.5 KB  |  467 lines

  1. /************************************************************************
  2.  *                                    *
  3.  *                N O T I C E                *
  4.  *                                    *
  5.  *            Copyright Abandoned, 1987, Fred Fish        *
  6.  *                                    *
  7.  *    This previously copyrighted work has been placed into the    *
  8.  *    public domain by the author (Fred Fish) and may be freely used    *
  9.  *    for any purpose, private or commercial.  I would appreciate    *
  10.  *    it, as a courtesy, if this notice is left in all copies and    *
  11.  *    derivative works.  Thank you, and enjoy...            *
  12.  *                                    *
  13.  *    The author makes no warranty of any kind with respect to this    *
  14.  *    product and explicitly disclaims any implied warranties of    *
  15.  *    merchantability or fitness for any particular purpose.        *
  16.  *                                    *
  17.  ************************************************************************
  18.  */
  19.  
  20. /*
  21.  *  FILE
  22.  *
  23.  *    c2c.c   test complex to complex math functions
  24.  *
  25.  *  KEY WORDS
  26.  *
  27.  *    portable math library
  28.  *    test functions
  29.  *
  30.  *  DESCRIPTION
  31.  *
  32.  *    Tests double precision functions for the Portable Math
  33.  *    Library.  Tests those functions which expect a single
  34.  *    double precision complex argument and return a double
  35.  *    precision complex result.
  36.  *
  37.  *    Most of the test data in the current data file (c2c.dat)
  38.  *    was generated using double precision FORTRAN arithmetic
  39.  *    on a Decsystem-20.
  40.  *
  41.  *    Note that the ordering of functions is important for
  42.  *    optimum error information.  Since some functions call
  43.  *    others in the library, the functions being called should
  44.  *    be tested first.  Naturally, an error in a lower level
  45.  *    function will cause propagation of errors up to higher
  46.  *    level functions.
  47.  *
  48.  *  USAGE
  49.  *
  50.  *    c2c [-esv] [-l limit]
  51.  *
  52.  *        -e    =>    force error for each test
  53.  *                to verify error handling
  54.  *
  55.  *        -l    =>    report errors greater than
  56.  *                specified limit (default 10**-6)
  57.  *
  58.  *        -s    =>    print summary after tests
  59.  *
  60.  *        -v    =>    print each function, argument,
  61.  *                and result
  62.  *
  63.  *    Test directives are read from the standard input, which
  64.  *    may be redirected to the provided test file (c2c.dat),
  65.  *    and any relative errors are automatically written to standard
  66.  *    output if they exceed a maximum allowable limit.
  67.  *    Each test directive has the form:
  68.  *
  69.  *        <name> <argument> <expected result>
  70.  *
  71.  *    Each field is separated by a one or more space character(s).
  72.  *    Both the argument and the expected result are given
  73.  *    in the form:
  74.  *
  75.  *        <real> <imag>
  76.  *
  77.  *    where <real> is the real part and <imag> is the
  78.  *    imaginary part, separated by one or more spaces.
  79.  *        
  80.  *        
  81.  *  NOTE
  82.  *
  83.  *    This program uses both the csubt and the cdiv routines,
  84.  *    which are pml functions!.  Thus if either of these screw
  85.  *    up, the results will be unpredictable.  BEWARE!
  86.  *
  87.  *  PROGRAMMER
  88.  *
  89.  *    Fred Fish
  90.  *    Tempe, Az 85281
  91.  *
  92.  */
  93.  
  94.  
  95. #include <stdio.h>
  96. #include <math.h>
  97. #include "pml.h"
  98.  
  99. #ifdef atarist
  100. #define STDERR    stdout
  101. #else
  102. #define STDERR stderr
  103. #endif
  104.  
  105. #define MAX_ABS_ERR 1.0e-6    /* Set to catch only gross errors */
  106.  
  107. static int vflag;        /* Flag for verbose option */
  108. static int eflag;        /* Simulate an error to error printout */
  109. static int sflag;        /* Flag to show final statistics */
  110.  
  111. static double max_abs_err = MAX_ABS_ERR;
  112.  
  113. /*
  114.  *    External functions which are used internally.
  115.  */
  116.  
  117. extern char *strtok ();
  118. extern double atof ();
  119. extern double cabs ();
  120. extern COMPLEX csubt ();
  121. extern COMPLEX cdiv ();
  122.  
  123. /*
  124.  *    External functions to be tested.
  125.  */
  126.  
  127. extern COMPLEX cacos();
  128. extern COMPLEX casin();
  129. extern COMPLEX catan();
  130. extern COMPLEX ccos();
  131. extern COMPLEX ccosh();
  132. extern COMPLEX cexp();
  133. extern COMPLEX clog();
  134. extern COMPLEX crcp();
  135. extern COMPLEX csin();
  136. extern COMPLEX csinh();
  137. extern COMPLEX csqrt();
  138. extern COMPLEX ctan();
  139. extern COMPLEX ctanh();
  140.  
  141.  
  142. /*
  143.  *    Define all recognized test functions.  Each function
  144.  *    must have an entry in this table, where each
  145.  *    entry contains the information specified in the 
  146.  *    structure "test".
  147.  *
  148.  */
  149.  
  150. struct test {            /* Structure of each function to be tested */
  151.     char *name;            /* Name of the function to test */
  152.     COMPLEX (*func)();        /* Pointer to the function's entry point */
  153.     double max_err;        /* Error accumulator for this function */
  154. };
  155.  
  156. static struct test tests[] = {    /* Table of all recognized functions */
  157.     "cacos", cacos, 0.0,     /* Complex arc cosine */
  158.     "casin", casin, 0.0,     /* Complex arc sine */
  159.     "catan", catan, 0.0,     /* Complex arc tangent */
  160.     "ccos", ccos, 0.0,         /* Complex cosine */
  161.     "ccosh", ccosh, 0.0,    /* Complex hyperbolic cosine */
  162.     "cexp", cexp, 0.0,         /* Complex exponential */
  163.     "clog", clog, 0.0,         /* Complex natural logarithm */
  164.     "crcp", crcp, 0.0,         /* Complex reciprocal */
  165.     "csin", csin, 0.0,         /* Complex sine */
  166.     "csinh", csinh, 0.0,     /* Complex hyperbolic sine */
  167.     "csqrt", csqrt, 0.0,     /* Complex square root */
  168.     "ctan", ctan, 0.0,         /* Complex tangent */
  169.     "ctanh", ctanh, 0.0,     /* Complex hyperbolic tangent */
  170.     NULL, NULL, 0.0        /* Function list end marker */
  171. };
  172.  
  173.  
  174. /*
  175.  *  FUNCTION
  176.  *
  177.  *    main   entry point for c2c test utility
  178.  *
  179.  *  PSEUDO CODE
  180.  *
  181.  *    Begin main
  182.  *        Process any options in command line.
  183.  *        Do all tests requested by stdin directives.
  184.  *        Report final statistics (if enabled).
  185.  *    End main
  186.  *
  187.  */
  188.  
  189. main (argc, argv)
  190. int argc;
  191. char *argv[];
  192. {
  193.     ENTER ("main");
  194.     DEBUGWHO (argv[0]);
  195.     options (argc, argv);
  196.     dotests (argv);
  197.     statistics ();
  198.     LEAVE ();
  199. }
  200.  
  201.  
  202. /*
  203.  *  FUNCTION
  204.  *
  205.  *    dotests   process each test from stdin directives
  206.  *
  207.  *  ERROR REPORTING
  208.  *
  209.  *    Note that in most cases, the error criterion is based
  210.  *    on relative error, defined as:
  211.  *
  212.  *        error = (result - expected) / expected
  213.  *
  214.  *    Naturally, if the expected result is zero, some
  215.  *    other criterion must be used.  In this case, the
  216.  *    absolute error is used.  That is:
  217.  *
  218.  *        error = result
  219.  *
  220.  *  PSEUDO CODE
  221.  *
  222.  *    Begin dotests
  223.  *        While a test directive is successfully read from stdin
  224.  *        Default function name to "{null}"
  225.  *        Default real part of argument to 0.0
  226.  *        Default imaginary part of argument to 0.0
  227.  *        Default expected result to 0.0
  228.  *        Extract function name, argument and expected result
  229.  *        Lookup test in available test list
  230.  *        If no test was found then
  231.  *            Tell user that unknown function was specified
  232.  *        Else
  233.  *            Call function with argument and save result
  234.  *            If the verify flag is set then
  235.  *            Print function name, argument, and result
  236.  *            End if
  237.  *            If the expected result is not zero then
  238.  *            Compute the relative error
  239.  *            Else
  240.  *            Use the absolute error
  241.  *            End if
  242.  *            Get absolute value of error
  243.  *            If error exceeds limit or error force flag set
  244.  *            Print error notification on stderr
  245.  *            End if
  246.  *            If this error is max for given function then
  247.  *            Remember this error for summary
  248.  *            End if
  249.  *        End if
  250.  *        End while
  251.  *    End dotests
  252.  *
  253.  */
  254.  
  255.  
  256. dotests (argv)
  257. char *argv[];
  258. {
  259.     char buffer[256];        /* Directive buffer */
  260.     char function[64];        /* Specified function name */
  261.     COMPLEX argument;        /* Specified function argument */
  262.     COMPLEX expected;        /* Specified expected result */
  263.     COMPLEX result;        /* Actual result */
  264.     COMPLEX error;        /* Relative or absolute error */
  265.     double abs_err;        /* Absolute value of error */
  266.     struct test *testp;        /* Pointer to function test */
  267.     struct test *lookup ();    /* Returns function test pointer */
  268.     register char *strp;    /* Pointer to next token in string */
  269.  
  270. #ifdef MJR
  271.     FILE * save_stdin, * re_stdin;
  272.     save_stdin = stdin;
  273.     re_stdin = freopen("c2c.dat","r",stdin);
  274.     if( re_stdin == (FILE *)NULL ) {
  275.     exit(-33);
  276.     }
  277. #endif
  278.     ENTER ("dotests");
  279.     while (fgets (buffer, sizeof(buffer), stdin) != NULL) {
  280.     strcpy (function, "{null}");
  281.     argument.real = argument.imag = 0.0;
  282.     expected.real = expected.imag = 0.0;
  283.     sscanf (buffer, "%s %le %le %le %le", function,
  284.     &argument.real, &argument.imag, &expected.real, &expected.imag);
  285.         testp = lookup (function);
  286.         if (testp == NULL) {
  287.             fprintf (STDERR, "%s: unknown function \"%s\".\n",
  288.             argv[0], function);
  289.         } else {
  290.         result = (*testp -> func)(argument);
  291.         if (vflag) {
  292.             printf ("%s(%le + j %le) \n   = %30.23le + j %30.23le.\n",
  293.         function, argument.real, argument.imag, result.real,
  294.         result.imag);
  295.         }
  296.         if (expected.real != 0.0 || expected.imag != 0.0) {
  297.         error = csubt (result, expected);
  298.         error = cdiv (error, expected);
  299.         } else {
  300.         error = result;
  301.         }
  302.         abs_err = cabs (error);
  303.             if ((abs_err > max_abs_err) || eflag) {
  304.         fprintf (STDERR, "%s: error in \"%s\"\n", argv[0], function);
  305.         fprintf (STDERR, "\treal (arg)\t\t%25.20le\n", argument.real);
  306.         fprintf (STDERR, "\timag (arg)\t\t%25.20le\n", argument.imag);
  307.         fprintf (STDERR, "\treal (result)\t\t%25.20le\n",result.real);
  308.         fprintf (STDERR, "\timag (result)\t\t%25.20le\n",result.imag);
  309.         fprintf (STDERR, "\treal (expected)\t\t%25.20le\n",expected.real);
  310.         fprintf (STDERR, "\timag (expected)\t\t%25.20le\n",expected.imag);
  311.             }
  312.         if (abs_err > testp -> max_err) {
  313.             testp -> max_err = abs_err;
  314.         }
  315.         }
  316.     }
  317. #ifdef MJR
  318.     fclose( re_stdin );
  319. #endif
  320.     LEAVE ();
  321. }
  322.  
  323.  
  324. /*
  325.  *  FUNCTION
  326.  *
  327.  *    options   process command line options
  328.  *
  329.  *  PSEUDO CODE
  330.  *
  331.  *    Begin options
  332.  *        Reset all flags to FALSE by default
  333.  *        Initialize flag argument scan pointer
  334.  *        If there is a second command line argument then
  335.  *        If the argument specifies flags then
  336.  *            While there is an unprocessed flag
  337.  *            Switch on flag
  338.  *            Case "force error flag":
  339.  *                Set the "force error" flag
  340.  *                Break switch
  341.  *            Case "print summary":
  342.  *                Set "print summary" flag
  343.  *                Break switch
  344.  *            Case "verbose":
  345.  *                Set "verbose" flag
  346.  *                Break switch
  347.  *            Default:
  348.  *                Tell user unknown flag
  349.  *                Break switch
  350.  *            End switch
  351.  *            End while
  352.  *        End if
  353.  *        End if
  354.  *    End options
  355.  *
  356.  */
  357.  
  358.  
  359. options (argc, argv)
  360. int argc;
  361. char *argv[];
  362. {
  363.     register int flag;
  364.     extern int getopt ();
  365.     extern char *optarg;
  366.  
  367.     ENTER ("options");
  368.     eflag = sflag = vflag = FALSE;
  369.     while ((flag = getopt (argc, argv, "#:el:sv")) != EOF) {
  370.     switch (flag) {
  371.         case '#':
  372.             DEBUGPUSH (optarg);
  373.         break;
  374.         case 'e':
  375.         eflag = TRUE;
  376.         break;
  377.         case 'l':
  378.             sscanf (optarg, "%le", &max_abs_err);
  379.         DEBUG3 ("args", "max_abs_err = %le", max_abs_err);
  380.         break;
  381.         case 's':
  382.         sflag = TRUE;
  383.         break;
  384.         case 'v':
  385.         vflag = TRUE;
  386.         break;
  387.     }
  388.     }
  389.     LEAVE ();
  390. }
  391.  
  392.  
  393. /*
  394.  *  FUNCTION
  395.  *
  396.  *    loopup   lookup test in known test list
  397.  *
  398.  *  DESCRIPTION
  399.  *
  400.  *    Given the name of a desired test, looks up the test
  401.  *    in the known test list and returns a pointer to the
  402.  *    test structure.
  403.  *
  404.  *    Since the table is so small we simply use a linear
  405.  *    search.
  406.  *
  407.  *  PSEUDO CODE
  408.  *
  409.  *    Begin lookup
  410.  *        For each known test
  411.  *        If the test's name matches the desired test name
  412.  *            Return pointer to the test structure
  413.  *        End if
  414.  *        End for
  415.  *    End lookup
  416.  *
  417.  */
  418.  
  419. struct test *lookup (funcname)
  420. char *funcname;
  421. {
  422.     struct test *testp;
  423.     struct test *rtnval;
  424.  
  425.     ENTER ("lookup");
  426.     rtnval = (struct test *) NULL;
  427.     for (testp = tests; testp -> name != NULL && rtnval == NULL; testp++) {
  428.     if (!strcmp (testp -> name, funcname)) {
  429.         rtnval = testp;
  430.      }
  431.     }
  432.     LEAVE ();
  433.     return (rtnval);
  434. }
  435.  
  436.  
  437. /*
  438.  *  FUNCTION
  439.  *
  440.  *    statistics   print final statistics if desired
  441.  *
  442.  *  PSEUDO CODE
  443.  *
  444.  *    Begin statistics
  445.  *        If a final statistics (summary) is desired then
  446.  *        For each test in the known test list
  447.  *            Print the maximum error encountered
  448.  *        End for
  449.  *        End if
  450.  *    End statistics
  451.  *
  452.  */
  453.  
  454. statistics ()
  455. {
  456.     struct test *tp;
  457.  
  458.     ENTER ("statistics");
  459.     if (sflag) {
  460.         for (tp = tests; tp -> name != NULL; tp++) {
  461.         printf ("%s:\tmaximum relative error %le\n", 
  462.             tp -> name, tp -> max_err);
  463.     }
  464.     }
  465.     LEAVE ();
  466. }
  467.